﻿// *****************************************************************
//    Copyright (c) Microsoft. All rights reserved.
//    This code is licensed under the Apache License, Version 2.0.
//    THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
//    ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
//    IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
//    PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
// *****************************************************************

/****************************************************************************
 * SparseSequenceBVTTestCases.cs
 * 
 * This file contains the Sparse Sequence BVT test case validation.
 * 
******************************************************************************/

using System;
using System.Text;
using System.Linq;
using System.Collections.Generic;

using Bio;
using Bio.TestAutomation.Util;
using Bio.Util.Logging;

using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
using System.Runtime.Serialization;

namespace Bio.TestAutomation
{
    /// <summary>
    /// Test Automation code for MBF Sparse Sequence BVT level validations
    /// </summary>
    [TestClass]
    public class SparseSequenceBvtTestCases
    {

        #region Global Variables

        ASCIIEncoding encodingObj = new ASCIIEncoding();

        #endregion Global Variables

        #region Constructor

        /// <summary>
        /// Static constructor to open log and make other settings needed for test
        /// </summary>
        static SparseSequenceBvtTestCases()
        {
            Trace.Set(Trace.SeqWarnings);
            if (!ApplicationLog.Ready)
            {
                ApplicationLog.Open("bio.automation.log");
            }
        }

        #endregion Constructor

        #region Sparse Sequence BVT Test Cases

        /// <summary>
        /// Creates sparse sequence object and validates the constructor.
        /// Validates if all items are present in sparse sequence instance.
        /// </summary>
        [TestMethod]
        [Priority(0)]
        [TestCategory("Priority0")]
        public void ValidateDnaSparseSequenceConstAlp()
        {
            SparseSequence sparseSeq = new SparseSequence(Alphabets.DNA);
            Assert.IsNotNull(sparseSeq);
            Assert.AreEqual(0, sparseSeq.Count);
            Assert.IsNotNull(sparseSeq.Statistics);

            Console.WriteLine("SparseSequence BVT: Validation of SparseSequence(alp) constructor is completed");
            ApplicationLog.WriteLine("SparseSequence BVT: Validation of SparseSequence(alp) constructor is completed");
        }

        /// <summary>
        /// Creates sparse sequence object and validates the constructor with Index.
        /// Validates if all items are present in sparse sequence instance.
        /// </summary>
        [TestMethod]
        [Priority(0)]
        [TestCategory("Priority0")]
        public void ValidateDnaSparseSequenceConstAlpIndex()
        {
            SparseSequence sparseSeq = new SparseSequence(Alphabets.DNA, 0);
            Assert.IsNotNull(sparseSeq);
            Assert.AreEqual(0, sparseSeq.Count);
            Assert.IsNotNull(sparseSeq.Statistics);

            Console.WriteLine("SparseSequence BVT: Validation of SparseSequence(alp, index) constructor is completed");
            ApplicationLog.WriteLine("SparseSequence BVT: Validation of SparseSequence(alp, index) constructor is completed");
        }

        /// <summary>
        /// Creates sparse sequence object and validates the constructor with Index, byte.
        /// Validates if all items are present in sparse sequence instance.
        /// </summary>
        [TestMethod]
        [Priority(0)]
        [TestCategory("Priority0")]
        public void ValidateDnaSparseSequenceConstAlpIndexByte()
        {
            byte[] byteArrayObj = encodingObj.GetBytes("AGCT");
            SparseSequence sparseSeq = new SparseSequence(Alphabets.DNA, 1, byteArrayObj[0]);
            Assert.IsNotNull(sparseSeq);
            Assert.IsNotNull(sparseSeq.Statistics);
            SequenceStatistics seqStatObj = sparseSeq.Statistics;
            Assert.AreEqual(1, seqStatObj.GetCount('A'));

            Console.WriteLine("SparseSequence BVT: Validation of SparseSequence(alp, index, byte) constructor is completed");
            ApplicationLog.WriteLine("SparseSequence BVT: Validation of SparseSequence(alp, index, byte) constructor is completed");
        }

        /// <summary>
        /// Creates sparse sequence object and validates the constructor with Index, byte.
        /// Validates if all items are present in sparse sequence instance.
        /// </summary>
        [TestMethod]
        [Priority(0)]
        [TestCategory("Priority0")]
        public void ValidateDnaSparseSequenceConstAlpIndexByteList()
        {
            byte[] byteArrayObj = encodingObj.GetBytes("AGCT");

            IEnumerable<byte> seqItems =
                new List<Byte>() { byteArrayObj[0], byteArrayObj[1], byteArrayObj[2], byteArrayObj[3] };

            SparseSequence sparseSeq = new SparseSequence(Alphabets.DNA, 4, seqItems);
            Assert.IsNotNull(sparseSeq);
            Assert.IsNotNull(sparseSeq.Statistics);
            Assert.AreEqual(8, sparseSeq.Count);
            SequenceStatistics seqStatObj = sparseSeq.Statistics;
            Assert.AreEqual(1, seqStatObj.GetCount('A'));
            Assert.AreEqual(1, seqStatObj.GetCount('G'));
            Assert.AreEqual(1, seqStatObj.GetCount('C'));
            Assert.AreEqual(1, seqStatObj.GetCount('T'));

            Console.WriteLine("SparseSequence BVT: Validation of SparseSequence(alp, index, seq items) constructor is completed");
            ApplicationLog.WriteLine("SparseSequence BVT: Validation of SparseSequence(alp, index, seq items) constructor is completed");
        }

        /// <summary>
        /// Creates a sparse a sequence and inserts all sequence items of alphabet. 
        /// Validates various properties present in the sparse class.
        /// </summary>
        [TestMethod]
        [Priority(0)]
        [TestCategory("Priority0")]
        public void ValidateDnaSparseSequenceProperties()
        {
            IAlphabet alphabet = Alphabets.DNA;

            // Create sparse sequence object
            int insertPosition = 0;
            // Create sequence item list
            IList<byte> sequenceList = new List<byte>();

            foreach (byte item in alphabet)
            {
                sequenceList.Add(item);
            }

            // Store sequence item in sparse sequence object using list of sequence items
            SparseSequence sparseSequence =
                new SparseSequence(alphabet, insertPosition, sequenceList);

            //Validate all properties
            Assert.AreEqual(alphabet.Count + insertPosition, sparseSequence.Count);
            Assert.AreEqual(alphabet, sparseSequence.Alphabet);
            Assert.IsTrue(string.IsNullOrEmpty(sparseSequence.ID));
            Assert.IsNotNull(sparseSequence.Metadata);
            Assert.IsNotNull(sparseSequence.Statistics);
            Assert.IsNotNull(sparseSequence.GetKnownSequenceItems());

            Console.WriteLine(
                "SparseSequence BVT: Validation of all properties of sparse sequence instance is completed");
            ApplicationLog.WriteLine(
                "SparseSequence BVT: Validation of all properties of sparse sequence instance is completed");
        }

        /// <summary>
        /// Creates a sparse sequence and validates IndexOfNonGap method
        /// </summary>
        [TestMethod]
        [Priority(0)]
        [TestCategory("Priority0")]
        public void ValidateSparseSequenceIndexOfNonGap()
        {
            SparseSequence sparseSeqObj = new SparseSequence(Alphabets.DNA, 10);
            sparseSeqObj[8] = Alphabets.DNA.Gap;
            sparseSeqObj[9] = Alphabets.DNA.A;

            Assert.AreEqual(9, sparseSeqObj.IndexOfNonGap(8));
            Assert.AreEqual(9, sparseSeqObj.IndexOfNonGap(9));

            Console.WriteLine(
                "SparseSequenceBVT: Validation of IndexOfNonGap(startPos) method successfully completed");
            ApplicationLog.WriteLine(
                "SparseSequenceBVT: Validation of IndexOfNonGap(startPos) method successfully completed");
        }

        /// <summary>
        /// Creates a sparse sequence and validates LastIndexOfNonGap method
        /// </summary>
        [TestMethod]
        [Priority(0)]
        [TestCategory("Priority0")]
        public void ValidateSparseSequenceLastIndexOfNonGap()
        {
            SparseSequence sparseSeqObj = new SparseSequence(Alphabets.DNA, 10);
            sparseSeqObj[2] = Alphabets.DNA.Gap;
            sparseSeqObj[1] = Alphabets.DNA.A;

            Assert.AreEqual(1, sparseSeqObj.LastIndexOfNonGap(2));
            Assert.AreEqual(1, sparseSeqObj.LastIndexOfNonGap(1));

            Console.WriteLine(
                "SparseSequenceBVT: Validation of LastIndexOfNonGap() method successfully completed");
            ApplicationLog.WriteLine(
                "SparseSequenceBVT: Validation of LastIndexOfNonGap() method successfully completed");
        }

        /// <summary>
        /// Creates a sparse sequence and validates IndexOfNonGap method
        /// </summary>
        [TestMethod]
        [Priority(0)]
        [TestCategory("Priority0")]
        public void ValidateSparseSequenceIndexOfNonGapNull()
        {
            SparseSequence sparseSeqObj = new SparseSequence(Alphabets.DNA, 2);
            sparseSeqObj[0] = Alphabets.DNA.Gap;
            sparseSeqObj[1] = Alphabets.DNA.A;

            Assert.AreEqual(1, sparseSeqObj.IndexOfNonGap());

            Console.WriteLine(
                "SparseSequenceBVT: Validation of IndexOfNonGap() method successfully completed");
            ApplicationLog.WriteLine(
                "SparseSequenceBVT: Validation of IndexOfNonGap() method successfully completed");
        }

        /// <summary>
        /// Creates a sparse sequence and validates LastIndexOfNonGap method
        /// </summary>
        [TestMethod]
        [Priority(0)]
        [TestCategory("Priority0")]
        public void ValidateSparseSequenceLastIndexOfNonGapNull()
        {
            SparseSequence sparseSeqObj = new SparseSequence(Alphabets.DNA, 2);
            sparseSeqObj[1] = Alphabets.DNA.Gap;
            sparseSeqObj[0] = Alphabets.DNA.A;

            Assert.AreEqual(0, sparseSeqObj.LastIndexOfNonGap());

            Console.WriteLine(
                "SparseSequenceBVT: Validation of LastIndexOfNonGap() method successfully completed");
            ApplicationLog.WriteLine(
                "SparseSequenceBVT: Validation of LastIndexOfNonGap() method successfully completed");
        }

        /// <summary>
        /// Creates a sparse sequence and validates LastIndexOfNonGap method
        /// </summary>
        [TestMethod]
        [Priority(0)]
        [TestCategory("Priority0")]
        public void ValidateSparseSequenceGetReversedSequence()
        {
            byte[] byteArrayObj = encodingObj.GetBytes("ACGT");

            IEnumerable<byte> seqItems =
                new List<Byte>() { byteArrayObj[0], byteArrayObj[1], byteArrayObj[2], byteArrayObj[3] };

            SparseSequence sparseSeqObj = new SparseSequence(Alphabets.DNA, 0, seqItems);
            ISequence revSeqObj = sparseSeqObj.GetReversedSequence();

            byteArrayObj = encodingObj.GetBytes("TGCA");

            for (int i = 0; i < byteArrayObj.Length; i++)
            {
                Assert.AreEqual(byteArrayObj[i], revSeqObj[i]);
            }
            Console.WriteLine(
                "SparseSequenceBVT: Validation of GetReversedSequence() method successfully completed");
            ApplicationLog.WriteLine(
                "SparseSequenceBVT: Validation of GetReversedSequence() method successfully completed");
        }

        /// <summary>
        /// Creates a sparse sequence and validates GetReverseComplementedSequence method
        /// </summary>
        [TestMethod]
        [Priority(0)]
        [TestCategory("Priority0")]
        public void ValidateSparseSequenceGetReversedComplementedSequence()
        {
            byte[] byteArrayObj = encodingObj.GetBytes("ACGT");

            IEnumerable<byte> seqItems =
                new List<Byte>() { byteArrayObj[0], byteArrayObj[1], byteArrayObj[2], byteArrayObj[3] };

            SparseSequence sparseSeqObj = new SparseSequence(Alphabets.DNA, 0, seqItems);
            ISequence revSeqObj = sparseSeqObj.GetReverseComplementedSequence();

            for (int i = 0; i < byteArrayObj.Length; i++)
            {
                Assert.AreEqual(byteArrayObj[i], revSeqObj[i]);
            }
            Console.WriteLine(
                "SparseSequenceBVT: Validation of GetReverseComplementedSequence() method successfully completed");
            ApplicationLog.WriteLine(
                "SparseSequenceBVT: Validation of GetReverseComplementedSequence() method successfully completed");
        }

        /// <summary>
        /// Creates a sparse sequence and validates GetKnownSequenceItems method
        /// </summary>
        [TestMethod]
        [Priority(0)]
        [TestCategory("Priority0")]
        public void ValidateSparseSequenceGetKnownSequenceItems()
        {
            byte[] byteArrayObj = encodingObj.GetBytes("ACGT");

            IEnumerable<byte> seqItems =
                new List<Byte>() { byteArrayObj[0], byteArrayObj[1], byteArrayObj[2], byteArrayObj[3] };

            SparseSequence sparseSeqObj = new SparseSequence(Alphabets.DNA, 0, seqItems);
            IList<IndexedItem<byte>> revSeqObj = sparseSeqObj.GetKnownSequenceItems();
            long i = 0;
            foreach (IndexedItem<byte> by in revSeqObj)
            {
                Assert.AreEqual(i, by.Index);
                Assert.AreEqual(byteArrayObj[i], by.Item);
                i++;
            }

            Console.WriteLine(
                "SparseSequenceBVT: Validation of GetKnownSequenceItems() method successfully completed");
            ApplicationLog.WriteLine(
                "SparseSequenceBVT: Validation of GetKnownSequenceItems() method successfully completed");
        }

        /// <summary>
        /// Creates a sparse sequence and validates GetComplementedSequence method
        /// </summary>
        [TestMethod]
        [Priority(0)]
        [TestCategory("Priority0")]
        public void ValidateSparseSequenceGetComplementedSequence()
        {
            byte[] byteArrayObj = encodingObj.GetBytes("ACGT");

            IEnumerable<byte> seqItems =
                new List<Byte>() { byteArrayObj[0], byteArrayObj[1], byteArrayObj[2], byteArrayObj[3] };

            SparseSequence sparseSeqObj = new SparseSequence(Alphabets.DNA, 0, seqItems);
            ISequence revSeqObj = sparseSeqObj.GetComplementedSequence();

            byteArrayObj = encodingObj.GetBytes("TGCA");

            for (int i = 0; i < byteArrayObj.Length; i++)
            {
                Assert.AreEqual(byteArrayObj[i], revSeqObj[i]);
            }

            Console.WriteLine(
                "SparseSequenceBVT: Validation of GetComplementedSequence() method successfully completed");
            ApplicationLog.WriteLine(
                "SparseSequenceBVT: Validation of GetComplementedSequence() method successfully completed");
        }

        /// <summary>
        /// Creates a sparse sequence and validates GetSubSequence method
        /// </summary>
        [TestMethod]
        [Priority(0)]
        [TestCategory("Priority0")]
        public void ValidateSparseSequenceGetSubSequence()
        {
            List<byte> byteList = new List<byte>();
            byteList.Add(Alphabets.DNA.Gap);
            byteList.Add(Alphabets.DNA.G);
            byteList.Add(Alphabets.DNA.A);
            byteList.Add(Alphabets.DNA.Gap);
            byteList.Add(Alphabets.DNA.T);
            byteList.Add(Alphabets.DNA.C);
            byteList.Add(Alphabets.DNA.Gap);
            byteList.Add(Alphabets.DNA.Gap);

            SparseSequence sparseSeq = new SparseSequence(Alphabets.DNA, 0, byteList);

            ISequence result = sparseSeq.GetSubSequence(0, 3);
            Assert.AreEqual(3, result.Count);
            Assert.AreEqual(Alphabets.DNA.Gap, result[0]);
            Assert.AreEqual(Alphabets.DNA.G, result[1]);
            Assert.AreEqual(Alphabets.DNA.A, result[2]);

            result = sparseSeq.GetSubSequence(0, 0);
            Assert.AreEqual(0, result.Count);

            result = sparseSeq.GetSubSequence(3, 2);
            Assert.AreEqual(2, result.Count);
            Assert.AreEqual(Alphabets.DNA.Gap, result[0]);
            Assert.AreEqual(Alphabets.DNA.T, result[1]);

            Console.WriteLine(
                "SparseSequenceBVT: Validation of GetSubSequence() method successfully completed");
            ApplicationLog.WriteLine(
                "SparseSequenceBVT: Validation of GetSubSequence() method successfully completed");
        }

        /// <summary>
        /// Creates a sparse sequence and validates GetEnumerator method
        /// </summary>
        [TestMethod]
        [Priority(0)]
        [TestCategory("Priority0")]
        public void ValidateSparseSequenceGetEnumerator()
        {
            byte[] byteArrayObj = encodingObj.GetBytes("ACGT");

            IEnumerable<byte> seqItems =
                new List<Byte>() { byteArrayObj[0], byteArrayObj[1], byteArrayObj[2], byteArrayObj[3] };

            SparseSequence sparseSeqObj = new SparseSequence(Alphabets.DNA, 0, seqItems);
            IEnumerator<byte> seqObj = sparseSeqObj.GetEnumerator();
            int i = 0;
            while (seqObj.MoveNext())
            {
                Assert.AreEqual(byteArrayObj[i], seqObj.Current);
                i++;
            }
            i = 0;
            foreach (byte alp in sparseSeqObj)
            {
                Assert.AreEqual(byteArrayObj[i], alp);
                i++;
            }

            Console.WriteLine(
                "SparseSequenceBVT: Validation of GetEnumerator() method successfully completed");
            ApplicationLog.WriteLine(
                "SparseSequenceBVT: Validation of GetEnumerator() method successfully completed");
        }

        /// <summary>
        /// Validate by passing indexer value for read only indexer.
        /// Input Data : Valid Alphabet
        /// Output Data : Successfully set 
        /// </summary>
        [TestMethod]
        [Priority(0)]
        [TestCategory("Priority0")]
        public void ValidateSparseSequenceSetIndexer()
        {
            IAlphabet alphabet = Alphabets.DNA;

            // Create sequence item list
            List<byte> sequenceList = new List<byte>();
            foreach (byte item in alphabet)
            {
                sequenceList.Add(item);
            }

            // Store sequence item in sparse sequence object using list of sequence items
            SparseSequence sparseSeq = new SparseSequence(alphabet, 0, sequenceList);
            byte seqItem = new Sequence(Alphabets.DNA, "AGCT")[0];

            sparseSeq[0] = seqItem;
            Assert.AreEqual(65, sparseSeq[0]);

            Console.WriteLine(
                "SparseSequence BVT: Validation of Indexer successfully completed");
            ApplicationLog.WriteLine(
                "SparseSequence BVT: Validation of Indexer successfully completed");
        }

        #endregion
    }
}
